package com.synjones.zeuscloudapp.filter;

import com.alibaba.fastjson.JSON;
import com.synjones.core.util.StringUtil;
import com.synjones.zeuscloudapp.bean.MessageBean;
import com.synjones.zeuscloudapp.util.DataPack;
import com.synjones.zeuscloudapp.util.DigestUtil;
import com.synjones.zeuscloudapp.util.MessageInfoUtil;
import com.synjones.zeuscloudapp.util.StatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

/**
 * @author yys
 * Description: 请求过滤器
 * @date created in 10:07 2018-03-15
 * Modified by:
 */
@WebFilter(filterName = "RequestFilter", urlPatterns = "/*")
@Order(value = 1)
@Configuration
public class RequestFilter implements Filter {
    private static final Logger LOG = LoggerFactory.getLogger(RequestFilter.class);
    private static final String AND = "&";
    private static String[] notValidateData;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String notValidateDataStr = "/getConfig,/intranetConfig";
        notValidateData = notValidateDataStr.split(",");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        LOG.info("*************进入到请求过滤器**************");
        HttpServletRequest req = (HttpServletRequest) request;
        String path = req.getRequestURI();
        String data = req.getParameter("data");
        LOG.info("请求地址为：{}，传过来的data为：{}，传过来的sign为：{}", path, getShortLogString(data), req.getParameter("sign"));
        MessageBean messageInfo = MessageInfoUtil.getMessageInfo(req);
        if (!path.contains(".apk") && !path.contains(".png") && !path.contains(".css") && !path.contains(".js")
                && !path.contains("downloads") && !path.contains("comeIntoRecommend") && !path.contains(".ico")
                && !path.contains(".jpeg") && !path.contains(".gif") && !path.contains("h5")) {
            String validate = isValidRequest(req, path, messageInfo);
            if (!"true".equals(validate)) {
                HttpServletResponse res = (HttpServletResponse) response;
                res.setCharacterEncoding("UTF-8");
                res.setContentType("application/json; charset=utf-8");
                res.setStatus(HttpServletResponse.SC_OK);
                PrintWriter writer = res.getWriter();
                writer.write(validate);
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    private String getShortLogString(String log) {
        if (log != null && log.length() > 2000) {
            return log.substring(0, 1999);
        }
        return log;
    }

    private String isValidRequest(HttpServletRequest req, String path, MessageBean messageInfo) {
        DataPack data = null;
        if (StringUtil.isNullOrEmpty(messageInfo.getOrganizationCode(), messageInfo.getApiVersion()
                , messageInfo.getAppVersion(), messageInfo.getClientType(), messageInfo.getClientMark()
                , messageInfo.getMagic())) {
            LOG.info("提交数据项非法");
            return JSON.toJSONString(new DataPack(false, StatusEnum.PARAMS_ERROR.getMessage()));
        }
//        if (RedisUtil.getInstance().exists(messageInfo.getMagic())) {
//            return JSON.toJSONString(new DataPack(false, StatusEnum.RANDOM_REPEAT.getMessage()));
//        }
        if (isValidateData(path)) {
            if (StringUtil.isNullOrEmpty(req.getParameter("data"))) {
                LOG.info("data为空，提交数据项非法");
                data = new DataPack(false, StatusEnum.PARAMS_ERROR.getMessage());
            }
        }
        if (StringUtil.isNullOrEmpty(data)) {
            String localSign = getSign(getSignText(messageInfo, req.getParameter("data")), "synjones_dinning_1014");
            String sign = req.getParameter("sign");
            if (!localSign.equals(sign)) {
                LOG.info("{}签名错误，本地签名为：{}，业务系统签名为：{}", messageInfo.getClientType(), localSign, sign);
                return JSON.toJSONString(new DataPack(false, "签名错误"));
            }
        }
        //true 验证通过
        return StringUtil.isNullOrEmpty(data) ? "true" : JSON.toJSONString(data);
    }

    //true 验证data
    private static boolean isValidateData(String path) {
        for (String str : notValidateData) {
            if (path.contains(str)) {
                return false;
            }
        }
        return true;
    }

    private static String getSign(String planText, String hmacKey) {
        try {
            return DigestUtil.hmacSha1(planText, hmacKey);
        } catch (UnsupportedEncodingException ex) {
            LOG.error("签名错误");
        }
        return "";
    }

    private String getSignText(MessageBean messageInfo, String data) {
        StringBuilder sb = new StringBuilder();
        sb.append("organizationCode=").append(messageInfo.getOrganizationCode()).append(AND)
                .append("apiVersion=").append(messageInfo.getApiVersion()).append(AND)
//                .append("dateTime=").append(messageInfo.getDateTime()).append(AND)
                .append("appVersion=").append(messageInfo.getAppVersion()).append(AND)
                .append("clientType=").append(messageInfo.getClientType()).append(AND)
                .append("clientMark=").append(messageInfo.getClientMark()).append(AND)
//                .append("iplanetdirectorypro=").append(messageInfo.getIplanetdirectorypro()).append(AND)
                .append("imei=").append(messageInfo.getImei()).append(AND)
                .append("clientIp=").append(messageInfo.getClientIp()).append(AND)
                .append("magic=").append(messageInfo.getMagic()).append(AND)
                .append("data=").append(data).append(AND)
                .append("pwd=").append("Synjones_app_20180417100758");
        String signSource = sb.toString();
        //LOG.info("本地签名的原文是：{}", getShortLogString(signSource));
        return signSource;
    }

    @Override
    public void destroy() {

    }
}
